<?php

namespace backend\utils;

use backend\models\file\AttExtend;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\FileHelper;
use ZipArchive;

class FileUpUtil
{
    const CODE_ERROR = 0;
    const CODE_SUCCESS = 1;

    /**
     * 文件上传及入库 统一入口
     *
     * @time 2022-1-7
     */
    public static function file_to_db($field, $main_att_id, $table_field, $extensions = ["pdf", "doc", "docx", 'xls', 'xlsx'], $max_M = 50)
    {
        $files = isset($_FILES[$field]) ? $_FILES[$field] : null;

        // 是否是多文件上传
        $is_file_multi = is_array($files['error']);

        if ($is_file_multi) {
            if (!$files || !is_array($files) || $files['size'][0] == 0) {
                return [self::CODE_ERROR, "先选择文件", $_FILES];
            }
        } else {
            if (!$files || !is_array($files) || count($files) == 0) {
                return [self::CODE_ERROR, "先选择文件", $_FILES];
            }
        }

        if ($is_file_multi) {
            list($code, $msg, $data) = self::upload_multi($field, $extensions, $max_M);
        } else {
            list($code, $msg, $data2) = self::upload($field, $extensions, $max_M);
            $data[] = $data2;
        }

        if ($code != FileUpUtil::CODE_SUCCESS) {
            return [self::CODE_ERROR, "上传失败: {$msg}"];
        }

        $flag = true;
        $msg = "";
        foreach ($data as $v) {
            list($res, $msg) = self::uploadFileInfo([
                'main_att_id' => $main_att_id,
                'att_name' => $v['att_name'],
                'att_position' => $v['att_position'],
                'att_size' => (string)$v['att_size'],
                'att_type' => $v['att_type'],
                'file_name' => $v['file_name'],
                'table_field' => $table_field,
            ]);
            if (!$res) {
                $flag = false;
                break;
            }
        }

        if ($flag) {
            return [self::CODE_SUCCESS, "上传成功"];
        } else {
            // 入库失败 删除文件
            self::unlink_files($data);
            return [self::CODE_ERROR, "上传失败: {$msg}"];
        }
    }

    /**
     * 单文件 入库
     *
     * @time 2022-1-7
     */
    public static function uploadFileInfo($data)
    {
        $model = new AttExtend();

        $data['uuid'] = AppUtil::init_uuid();
        $data['status'] = AppUtil::STATUS_USE;
        $data['submit_time'] = AppUtil::get_format_time();

        $model->setAttributes($data);

        if ($model->validate() && $model->save()) {
            return [true, ''];
        } else {
            return [false, AppUtil::get_error_msg($model)];
        }
    }

    /**
     * 删除文件
     *
     * @time 2022-1-7
     */
    public static function delete_files($id)
    {
        $files = AttExtend::find()->where([
            'status' => AppUtil::STATUS_USE,
            'main_att_id' => $id,
        ])->asArray()->all();

        if (!$files) return 0;

        return AttExtend::updateAll(['status' => AppUtil::STATUS_VOID,], ['uuid' => ArrayHelper::getColumn($files, 'uuid')]);
    }


    /**
     * 单文件 上传
     *
     * @time 2022-1-6
     */
    public static function upload($field, $extensions = [], $max_M = 0)
    {
        if (!$max_M) {
            $max_M = 10 * 1024 * 1024;
        }

        $file = isset($_FILES[$field]) ? $_FILES[$field] : null;

        if (!$file || !is_array($file) || count($file) == 0) {
            return [self::CODE_ERROR, "先选择文件", $_FILES];
        }

        $file_error = $file['error'];
        $file_size = $file['size'];
        $file_name = $file['name'];
        $file_tmp_name = $file['tmp_name'];
        $extension = pathinfo($file_name, PATHINFO_EXTENSION);

        if ($file_error != 0) {
            return [self::CODE_ERROR, "上传失败: 未知错误", $file];
        }

        if ($file_size > (1024 * 1024 * $max_M)) {
            return [self::CODE_ERROR, "请上传{$max_M}兆以内的文件", $file];
        }

        if ($extensions && !in_array($extension, $extensions)) {
            $extensions_str = trim(implode(',', $extensions), ',');
            return [self::CODE_ERROR, "请上传{$extensions_str}文件", $file];// 请上传pdf,doc,docx,xls,xlsx,pptx文件
        }

        $date = date("Y-m-d");

        $path = '/files/' . $date . '/';
        $directory = AppUtil::get_web_path() . $path;

        if (!is_dir($directory)) {
            FileHelper::createDirectory($directory);
        }

        $create_file_name = date('YmdHis') . '_' . random_int(1111, 9999) . '.' . $extension;
        $file_path = $directory . $create_file_name;

        if (!move_uploaded_file($file_tmp_name, $file_path)) {
            return [self::CODE_ERROR, "上传失败2", $file];
        }

        $data = [
            'att_name' => $create_file_name,
            'att_position' => $path . $create_file_name,
            'att_size' => $file_size,
            'att_type' => $extension,
            'file_name' => $file_name,
        ];

        return [self::CODE_SUCCESS, "上传成功", $data];
    }

    /**
     * 多文件 上传
     *
     * @time 2020-12-18
     */
    public static function upload_multi($field, $extensions = [], $max_M = 0)
    {
        if (!$max_M) {
            $max_M = 10 * 1024 * 1024;
        }

        $files = isset($_FILES[$field]) ? $_FILES[$field] : null;

        if (!$files || !is_array($files) || count($files) == 0) {
            return [self::CODE_ERROR, "先选择文件", $_FILES];
        }

        foreach ($files['error'] as $k => $file_error) {

            $file_size = $files['size'][$k];
            $file_name = $files['name'][$k];
            $file_tmp_name = $files['tmp_name'][$k];
            $extension = pathinfo($file_name, PATHINFO_EXTENSION);

            if ($file_error != 0) {
                return [self::CODE_ERROR, "上传失败: 未知错误", $files];
            }

            if ($file_size > (1024 * 1024 * $max_M)) {
                return [self::CODE_ERROR, "请上传{$max_M}兆以内的文件", $files];
            }

            if ($extensions && !in_array($extension, $extensions)) {
                $extensions_str = trim(implode(',', $extensions), ',');
                return [self::CODE_ERROR, "请上传{$extensions_str}文件", $files];// 请上传pdf,doc,docx,xls,xlsx,pptx文件
            }

            $date = date("Y-m-d");

            $path = '/files/' . $date . '/';
            $directory = AppUtil::get_web_path() . $path;
            if (!is_dir($directory)) {
                FileHelper::createDirectory($directory);
            }

            $create_file_name = date('YmdHis') . '_' . random_int(1111, 9999) . '.' . $extension;
            $file_path = $directory . $create_file_name;

            if (!move_uploaded_file($file_tmp_name, $file_path)) {
                return [self::CODE_ERROR, "上传失败2", $files];
            }

            $data[] = [
                'att_name' => $create_file_name,
                'att_position' => $path . $create_file_name,
                'att_size' => $file_size,
                'att_type' => $extension,
                'file_name' => $file_name,
            ];

        }

        return [self::CODE_SUCCESS, "上传成功", $data];
    }

    /**
     * 删除入库失败文件
     *
     * @time 2022-1-7
     */
    public static function unlink_files($data)
    {
        if (isset($data['att_position'])) {
            @unlink(AppUtil::get_web_path() . $data['att_position']);
        } else {
            foreach ($data as $v) {
                @unlink(AppUtil::get_web_path() . $v['att_position']);
            }
        }
    }

    /**
     * 下载文件
     *
     * eg: FileUpUtil::download_file('/files/xxx.pdf',"教学任务导入模板.xlsx");
     *
     * @time 2022-1-11
     */
    public static function download_file($path, $file_name)
    {
        $download_file_flag = true;
        $path = AppUtil::get_web_path() . $path;
        try {
            Yii::$app->response->sendFile($path, $file_name)->send();
        } catch (\Exception $e) {
            // $e->getMessage()
            $download_file_flag = false;
        }

        return $download_file_flag;
    }

    /**
     * 打包下载
     *
     * @param $zipname string zip文件名
     * @param $file_array 要打包的文件 是一个二维数组的固定格式
     *
     * eg:
     *
     * $fileArr =
     * [
     *   ['file_path' => '/Users/b_tt/Downloads/zip_test/15000.xlsx', 'zip_path' => 'file1/15000.xlsx'],
     *   ['file_path' => '/Users/b_tt/Downloads/zip_test/11926.xlsx', 'zip_path' => 'file1/11926.xlsx'],
     *   ['file_path' => '/Users/b_tt/Downloads/zip_test/15000.xlsx', 'zip_path' => 'file2/15000.xlsx'],
     * ];
     *
     * @time 2022-1-11 PM
     */
    public static function zip_download_file($zipname, $file_array)
    {
        if (!is_array($file_array)) {
            echo "param error";
            exit;
        }
        if (!$file_array) {
            echo "下载文件不能为空";
            exit;
        }
        $zipname = AppUtil::get_web_path() . '/files/' . $zipname . '.zip';

        // 要使用该类，需要先启用 extension=php_zip.dll
        if (!extension_loaded("zip")) {
            echo "zip extension loaded fail";
            exit;
        }

        // 如果 zip_path 一样则会覆盖
        $count_values = array_count_values(ArrayHelper::getColumn($file_array, 'zip_path'));
        foreach ($count_values as $zip_path => $co) {
            $dir_name = pathinfo($zip_path, PATHINFO_DIRNAME);
            $ext = pathinfo($zip_path, PATHINFO_EXTENSION);
            $file_name = pathinfo($zip_path, PATHINFO_FILENAME);

            $i = 0;
            foreach ($file_array as $k => $v) {
                if ($v['zip_path'] == $zip_path) {
                    if ($i > 0) {
                        $file_array[$k]['zip_path'] = $dir_name . '/' . $file_name . "({$i})." . $ext;
                    }
                    $i++;
                }
            }
        }

        try {
            $zip = new ZipArchive();
            $res = $zip->open($zipname, ZipArchive::CREATE);
            if ($res === true) {
                foreach ($file_array as $file) {
                    // 这里将服务器上的文件添加到下载内容中，并重新赋值下载zip文件内该文件的路径
                    if (file_exists($file ['file_path'])) {
                        $zip->addFile($file ['file_path'], $file ['zip_path']);
                    }
                }
                $zip->close();
                // 下载
                Yii::$app->response->sendFile($zipname)->send();
            } else {
                echo 'create zip err ';
            }
        } catch (\Exception $e) {

        }

        //删除
        @unlink($zipname);
    }

    public static function getSystemName()
    {
        return strtolower(php_uname('s'));
    }


    public static function getFileName($filename)
    {
        $sys_name = self::getSystemName();
        return stripos($sys_name, 'win') !== false ? iconv('utf-8', 'gbk', $filename) : $filename;
    }

    public static function getFileName2($filename)
    {
        $sys_name = self::getSystemName();
        return $filename;
    }

    /**
     * @desc 创建目录
     * @return void
     * @Date: 2024/11/5
     */
    public static function make_dir($dir)
    {
        if (!is_dir($dir)) {
            FileHelper::createDirectory($dir);
        }
    }

    /**
     * @desc 没有此文件创建此文件及目录
     * @return void
     * @Date: 2024/11/5
     */
    public static function touch_file($file_path)
    {
        $file_dir = pathinfo($file_path, PATHINFO_DIRNAME);
        self::make_dir($file_dir);

        if (!file_exists($file_path)) {
            touch($file_path);
        }
    }
}
